package cn.edu.sjtu.se.dslab.DAO.achieve;


import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.transform.Transformers;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.hibernate3.HibernateQueryException;
import org.springframework.orm.hibernate3.HibernateSystemException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import cn.edu.sjtu.se.dslab.DAO.IBaseDAO;
import cn.edu.sjtu.se.dslab.actionbean.PageBean;
import cn.edu.sjtu.se.dslab.exception.DBException;
import cn.edu.sjtu.se.dslab.util.Const;
import cn.edu.sjtu.se.dslab.util.DBMessage;

/**
 * 	
 * 	数据处理层基类的实现类
 * 	@author 
 * 	@update 
 */
public class BaseDAOAchieve<T> extends HibernateDaoSupport implements IBaseDAO<T> {
	protected void initDao() {
		// do nothing
	}
	/**
	 * 	根据hql语句查询信息<BR>
	 * 	@param	hql语句
	 * 	@return 查询结果(泛型List)
	 */
	@SuppressWarnings("unchecked")
	public List<T> find(String hql)throws DBException
	{		
		try
		{
			//查询
			return this.getHibernateTemplate().find(hql);
		}
		catch(org.springframework.dao.CannotAcquireLockException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(org.springframework.orm.hibernate3.HibernateJdbcException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(DataAccessResourceFailureException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(HibernateQueryException e)
		{
			e.printStackTrace();
			//如果hql语句出现问题抛出DBException并且传入消息
			throw new DBException(DBMessage.EXECUTE_SELECT);
		}
		catch(Exception e)
		{
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}
	}

	/**
	 * 	根据hql语句查询信息<BR>
	 * 	@param	hql语句,参数
	 * 	@return 查询结果(泛型List)
	 */
	@SuppressWarnings("unchecked")
	public List<T> find(String hql, Object value)throws DBException
	{
		try
		{
			//查询
			return this.getHibernateTemplate().find(hql, value);
		}
		catch(DataAccessResourceFailureException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(HibernateQueryException e)
		{
			//如果hql语句出现问题抛出DBException并且传入消息
			throw new DBException(DBMessage.EXECUTE_SELECT);
		}		
		catch(Exception e)
		{
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}
	}

	/**
	 * 	根据hql语句查询信息<BR>
	 * 	@param	hql语句，参数（多个）
	 * 	@return 查询结果(泛型List)
	 */
	@SuppressWarnings("unchecked")
	public List<T> find(String hql, Object[] values)throws DBException
	{
		try
		{
			//查询	
			return this.getHibernateTemplate().find(hql, values);
		}
		catch(DataAccessResourceFailureException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(HibernateQueryException e)
		{
			//如果hql语句出现问题抛出DBException并且传入消息
			throw new DBException(DBMessage.EXECUTE_SELECT);
		}		
		catch(Exception e)
		{
			//session.close();
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}
	}

	/**
	 * 	根据hql语句查询信息<BR>
	 * 	@param	hql语句，参数（多个）
	 * 	@return 查询结果(泛型List)
	 */
	public String findSingleValue(String sql)throws DBException
	{		
		//查询
		List list = this.findBySql(sql);
		
		//如果没有查询结果
		if(list.size()==0)
		{
			//返回空
			return null;
		}
		else
		{
			//获取列表第一个元素
			List li = (List)list.get(0);
			
			//如果值为空
			if(li.get(0)==null)
			{
				//返回空
				return null;
			}
			else
			{
				//返回查询结果
				return li.get(0).toString();
			}		
		}		
	}
	
	/**
	 * 	根据hql语句查询要更新的单条记录信息<BR>
	 * 	@param	hql语句，参数（多个）
	 * 	@return 查询结果(泛型List)
	 */
	@SuppressWarnings("unchecked")
	public List<String> findSingleRecord(String sql)throws DBException
	{
		//查询
		List list = this.findBySql(sql);
		
		if(list.size()==0)
		{
			return null;
		}
		
		//获取列表第一个元素
		List li = (List)list.get(0);
		
		//返回查询结果	
		return li;		
	}
	
	

	/**
	 * 	新增<BR>
	 * 	@param	数据集
	 * 	@throws	DBException
	 */
	public void save(T obj) throws DBException 
	{		
		//获得session对象
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		//创建删除事务
		Transaction tx = null;
		try
		{
				//开始一个事务
				tx = session.beginTransaction();
				//执行事务
				getHibernateTemplate().save(obj);
				//提交事务
				tx.commit();
		}
		catch(DataAccessResourceFailureException e)
		{
			if(tx != null){//出现异常则撤销事务
				tx.rollback();
			}
			//如果连接数据库失败抛出DBException并且传入消息
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		
		catch(DataIntegrityViolationException e)
		{
			if(tx != null){//出现异常则撤销事务
				tx.rollback();
			}
			//主键冲突
			throw new DBException(DBMessage.E_NOT_UNIQUE);
		}
		catch(HibernateSystemException e)
		{
			if(tx != null){//出现异常则撤销事务
				tx.rollback();
			}
			//执行错误
			throw new DBException(DBMessage.EXECUTE_UPDATE);
		}
		catch(Exception e)
		{
			if(tx != null){//出现异常则撤销事务
				tx.rollback();
			}
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}finally{
			try
			{
				//关闭session
				session.close();
			}
			catch(Exception e)
			{
				//如果连接数据库失败抛出DBException并且传入消息Code
				throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
			}
		}
	}

	
	/**
	 * 	根据hql语句查询信息（不分页）<BR>
	 * 	@param	hql语句
	 * 	@return 查询结果(List类型List)
	 */
	@SuppressWarnings("unchecked")
	public List<List<String>> findByHql(String hql) throws DBException 
	{
		//定义session对象
		Session session = getSession();

		try
		{
			//定义Query对象
			Query q = session.createQuery(hql).setResultTransformer(Transformers.TO_LIST);

			//查询数据
			List list = q.list();

			//返回查询结果
			return list;
		}
		catch(JDBCConnectionException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(LockAcquisitionException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(HibernateQueryException e)
		{
			//如果hql语句出现问题抛出DBException并且传入消息
			throw new DBException(DBMessage.EXECUTE_SELECT);
		}
		catch(Exception e)
		{
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}

		//程序结束时关闭session
		finally
		{
			try
			{
				//关闭session
				session.close();
			}
			catch(Exception e)
			{
				//如果连接数据库失败抛出DBException并且传入消息Code
				throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
			}
		}
	}

	/**
	 * 	根据hql语句查询信息（分页）<BR>
	 * 	@param	当前页起始索引hql语句
	 * 	@return 查询结果(List类型List)
	 */
	@SuppressWarnings("unchecked")
	public PageBean findByHqlPage(int pageNum, String hql)
			throws DBException 
	{
		//定义返回值
        PageBean pageBean = new PageBean();
        //总记录数
		int allRow = findByHql(hql).size();
		
		//总页数
		int totalPage = PageBean.countTotalPage(Const.PAGESIZE, allRow);
        
		//当前页开始记录
		int start = PageBean.countOffset(Const.PAGESIZE,pageNum);
		
		//当前页号
        int currentPage = PageBean.countCurrentPage(pageNum);
            
		//定义session对象
		Session session = getSession();

		try
		{
			//定义Query对象
			Query q = session.createQuery(hql);

			//设置分页操作当前也的开始项
			q.setFirstResult(start);
			
			//设置页面大小
			q.setMaxResults(Const.PAGESIZE);
			//查询数据
			List list = q.list();

			//把分页信息保存到Bean中
	        // 页面大小
	        pageBean.setPageSize(Const.PAGESIZE);

	        //页面起始记录数
	        pageBean.setStart(start);
	    
	        //页面结束记录数
	        pageBean.setEnd(start+list.size());

	        // 设置当前页
	        pageBean.setCurrentPage(currentPage);

	        // 设置总记录数
			pageBean.setAllRow(allRow);

			// 设置总页数
	        pageBean.setTotalPage(totalPage);

	        // 设置结果集
	        pageBean.setList(list);
	        
			//返回list
			return pageBean;
		}
		catch(JDBCConnectionException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(LockAcquisitionException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(HibernateQueryException e)
		{
			//如果hql语句出现问题抛出DBException并且传入消息
			throw new DBException(DBMessage.EXECUTE_SELECT);
		}
		catch(Exception e)
		{
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}

		//程序结束时关闭session
		finally
		{
			try
			{
				//关闭session
				session.close();
			}
			catch(Exception e)
			{
				//如果连接数据库失败抛出DBException并且传入消息Code
				throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
			}
		}
	}

	/**
	 * 	根据hql语句查询信息（不分页）<BR>
	 * 	@param	hql语句
	 * 	@return 查询结果(List类型List)
	 */
	@SuppressWarnings("unchecked")
	public List<List<String>> findBySql(String sql) throws DBException 
	{
		//定义session对象
		Session session = getSession();

		try
		{
			//定义Query对象
			Query q = session.createSQLQuery(sql).setResultTransformer(Transformers.TO_LIST);

			//查询数据
			List list = q.list();

			//session.close();
			
			//返回查询结果
			return list;
			
		}
		catch(JDBCConnectionException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(LockAcquisitionException e)
		{
			//如果连接数据库失败抛出DBException并且传入消息Code
			throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
		}
		catch(HibernateQueryException e)
		{
			//如果hql语句出现问题抛出DBException并且传入消息
			throw new DBException(DBMessage.EXECUTE_SELECT);
		}
		catch(Exception e)
		{
			//出现除以上情况的其它情况抛出异常对象
			throw new DBException(DBMessage.E_OTHER);
		}

		//程序结束时关闭session
		finally
		{
			try
			{
				//关闭session
				session.close();
			}
			catch(Exception e)
			{
				//如果连接数据库失败抛出DBException并且传入消息Code
				throw new DBException(DBMessage.DBCONNECT_RETRYOVER);
			}
		}
	}

	
	
	
}

